package block


import (
	"errors"
	bolt "github.com/github-boltdb-master"
)

const CHAIN_DB_PATH = "./chain.db"
const BUCKET_BLOCK = "chain_block"
const BUCKET_STATUS = "chain_status"
const LAST_HASH = "lash_hash"

//区块链的作用：管理区块
type BlockChain struct {
	DB *bolt.DB
	LastHash []byte
}
//创建带有创世区块的区块链
func NewBlockChain(data []byte)(*BlockChain,error){
	//db 打开好的一个数据库
	db,err := bolt.Open(CHAIN_DB_PATH,0600,nil)
	if err != nil{
		return nil,err
	}
	var lasthash []byte
	err = db.Update(func(tx *bolt.Tx) error {
		//找桶1，为了存区块信息
		bk := tx.Bucket([]byte(BUCKET_BLOCK))
		//没有桶1
		if bk == nil{
			//创建一个带有创世区块的区块链
			genesis := GenesisBlock(data)
			//创建桶1
			bk, err := tx.CreateBucket([]byte(BUCKET_BLOCK))
			if err != nil{
				return err
			}
			//把创世区块转[]byte Serialize
			serialize, err := genesis.Serialize()
			if err != nil{
				return err
			}
			bk.Put(genesis.Hash,serialize)
			//创建桶2，为了存储最后一个区块的hahs值
			bk2, err := tx.CreateBucket([]byte(BUCKET_STATUS))
			if err != nil{
				return err
			}
			bk2.Put([]byte(LAST_HASH),genesis.Hash)
			lasthash = genesis.Hash
		}else {
			bk2 := tx.Bucket([]byte(BUCKET_STATUS))
			hash := bk2.Get([]byte(LAST_HASH))
			lasthash = hash
		}
		return nil
	})
	//初始化
	bc := BlockChain{
		DB: db,
		LastHash: lasthash,
	}
	return &bc,err
}
/**
向区块链里添加新区块
 */
func (bc *BlockChain)AddBlock(data []byte)error{
	//1.创建新区块
	newBlock := NewBlock(data, bc.LastHash)
	//2.添加到区块链中 更新 增删改
	err := bc.DB.Update(func(tx *bolt.Tx) error {
		bk := tx.Bucket([]byte(BUCKET_BLOCK))
		if bk == nil{
			return errors.New("没有桶1，无法添加")
		}
		serialize, err := newBlock.Serialize()
		if err != nil{
			return err
		}
		//存数据
		bk.Put(newBlock.Hash,serialize)
		bk2 := tx.Bucket([]byte(BUCKET_STATUS))
		if bk == nil{
			return errors.New("没有桶2，无法添加")
		}
		bk2.Put([]byte(LAST_HASH),newBlock.Hash)
		bc.LastHash = newBlock.Hash
		return nil
	})
	return err
}
//为了创建迭代器
func(bc *BlockChain)Iterator()*ChainIterator{
	iterator := ChainIterator{
		DB:bc.DB,
		CurrentHash:bc.LastHash,
	}
	return &iterator
}
//func xx()[]byte{
//	var a = []byte{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
//	return a
//}
